package com.sw.c.service.impl;

import com.sun.deploy.net.URLEncoder;
import com.sw.c.mapper.FileInfoMapper;
import com.sw.c.mapper.UserMapper;
import com.sw.c.pojo.entity.FileInfo;
import com.sw.c.pojo.entity.User;
import com.sw.c.service.FileInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Service
@Slf4j
public class FileInfoServiceImpl  implements FileInfoService {


    // 文件地址
    @Value("${file.filePath}")
    private String basePath;
    // 文件格式
    @Value("${file.format}")
    private String allowedExtensions;

    @Resource
    private FileInfoMapper fileInfoMapper;

    @Resource
    private UserMapper userMapper;

    /**
     * 文件上传
     * @param file
     * @param userId
     * @return
     */
    @Override
    public String upload(MultipartFile file, Integer userId) {

        User user = userMapper.getUserRoleId(userId);
        LocalDate currentDate = LocalDate.now();
        String yearMonthDay = currentDate.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        // 拼接年月日目录路径
        String directoryPath = basePath + "/" + yearMonthDay;

        //原始文件名
        String originalFilename = file.getOriginalFilename();
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        if (!isAllowedExtension(suffix)) {
            return "文件格式不支持，仅支持上传 " + allowedExtensions + " 格式的文件";
        }
        //使用UUID重新生成文件名，防止文件名称重复造成文件覆盖
        String fileName = UUID.randomUUID().toString() + suffix;
        // 创建目录对象
        File dir = new File(directoryPath);
        // 判断当前目录是否存在，不存在则创建
        if (!dir.exists()) {
            dir.mkdirs();
        }
        try {
            // 将文件保存到当日的文件夹中
            file.transferTo(new File(directoryPath + "/" + fileName));
            // 构建文件信息对象
            FileInfo fileInfo = new FileInfo();
            fileInfo.setFileName(fileName);
            fileInfo.setOriginalFilename(originalFilename);
            fileInfo.setFilePath(yearMonthDay + "/" + fileName); // 只保存相对路径
            fileInfo.setUploadingPerson(user.getUsername());
            fileInfo.setStates(1);
            fileInfo.setUploadTime(new Date());
            fileInfoMapper.insert(fileInfo);
            return "上传成功";
        } catch (IOException e) {
            e.printStackTrace();
            return "上传失败";
        }
    }

    /**
     * 文件下载
     * @param fileId
     * @param response
     */
    @Override
    public void fileDownload(Integer fileId, HttpServletResponse response) {

        FileInputStream fileInputStream = null;
        ServletOutputStream outputStream = null;
        FileInfo fileInfo = fileInfoMapper.getByIdPath(fileId);
        try {
            // 构建文件路径
            String filePath = basePath + "/" + fileInfo.getFilePath();
            String fileName = URLEncoder.encode( fileInfo.getOriginalFilename().trim(), "UTF-8");
            response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
            // 设置响应内容类型为文本文件
            response.setContentType("text/plain");
            fileInputStream = new FileInputStream(filePath);
            outputStream = response.getOutputStream();
            int len;
            byte[] bytes = new byte[1024];
            while ((len = fileInputStream.read(bytes)) != -1) {
                outputStream.write(bytes, 0, len);
                outputStream.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (outputStream != null) {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    private boolean isAllowedExtension(String extension) {
        List<String> allowedExtensionsList = Arrays.asList(allowedExtensions.split(","));
        return allowedExtensionsList.contains(extension);
    }
}
